import { ETTask } from "../../../Support/Share/Lib/Async/ETTask";
import { Exception, NullReferenceException } from "../../Object/Exception";
import { ATimer } from "../Timer/ATimer";
import { CoroutineLock } from "./CoroutineLock";

export class WaitCoroutineLockTimer extends ATimer<WaitCoroutineLock>
{
    protected override Run(waitCoroutineLock: WaitCoroutineLock) {
        if (waitCoroutineLock.IsDisposed()) {
            return;
        }
        waitCoroutineLock.SetException(new Exception("coroutine is timeout!"));
    }
}

export class WaitCoroutineLock {

    public static Create(): WaitCoroutineLock {
        let waitCoroutineLock = new WaitCoroutineLock();
        waitCoroutineLock.tcs = ETTask.Create();
        return waitCoroutineLock;
    }

    private tcs: ETTask<CoroutineLock>;

    public SetResult(coroutineLock: CoroutineLock) {
        if (this.tcs == null) {
            throw new NullReferenceException("SetResult tcs is null");
        }
        var t = this.tcs;
        this.tcs = null;
        t.SetResult(coroutineLock);
    }

    public SetException(exception) {
        if (this.tcs == null) {
            throw new NullReferenceException("SetException tcs is null");
        }
        var t = this.tcs;
        this.tcs = null;
        t.SetException(exception);
    }

    public IsDisposed(): boolean {
        return this.tcs == null;
    }

    public async Wait(): Promise<CoroutineLock> {
        return await this.tcs;
    }

}